// ****************************************************************************
//	Copyright (c) 2011 Daniel Watman
//	http://www.keycommander.net/
// ****************************************************************************
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//	
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//	
//	You should have received a copy of the GNU General Public License
//	along with this program.  If not, see <http://www.gnu.org/licenses/>.
// *********************************************************************
//	File:	usart.c
//	Purpose:	Basic functions for USART
//	Author:	Daniel Watman
//	Created: 2011.02.28
//	Updated:	2011.02.28
//	Version:	0.1
//	Target:	Atmel AVR XMEGA 128A1
//	Compiler: AVR-GCC
// *********************************************************************
//	Changes:
//		0.1	* Initial version
// *********************************************************************
//	To do:
//		* 
// *********************************************************************

#include <avr/io.h>
#include "types.h"

volatile char TXbuf[50], TXbuf_len;	// for test messages

void init_usart(void) {	// initialise serial ports
	// UART D0 (UART0) for debugging (115200 baud)
	PORTD.OUTSET = (1<<3);										// set PORTD pin 3 high (USARTD0 TX) before enabling output
	PORTD.DIRSET = (1<<3);										// set PORTD pin 3 as output (USARTD0 TX)
	USARTD0.BAUDCTRLB = ((-3 & 0x0f)<<4) | ((131 >> 8)&0x0f);	// set BSCALE and BSEL high bits (115200 baud)
	USARTD0.BAUDCTRLA = (131 & 0xff);							// set BSEL low bits (115200 baud)
	USARTD0.CTRLC = 0x03;										// set async UART, 8 bits, 1 stop, no parity
	USARTD0.CTRLB = 0x18;										// enable RX, TX. disable 2X speed, multiprocessor mode, 9-bit mode

	DMA.CTRL |= 0x80;		// enable DMA controller
}

// DMA transfer setup for sending string to UART
void dma_txbuf(DMA_CH_t *dma_ch, USART_t *uart, u08 trigger, void *buf, u08 length) {
	u32 src_addr, dest_addr;

	// ***NOTE*** ONLY WORKS IF ADDRESSES ARE UNDER 64kB limit
	src_addr = (u16)buf;
	dest_addr = (u16)&uart->DATA;

	dma_ch->ADDRCTRL = 0x10;	// no reload, increment source address, fixed destination
	dma_ch->TRFCNT = (u16)length;	// set no. bytes for block transfer

	dma_ch->SRCADDR0 = (src_addr >> 0*8 ) & 0xFF;	// source is buffer
	dma_ch->SRCADDR1 = (src_addr >> 1*8 ) & 0xFF;
	dma_ch->SRCADDR2 = (src_addr >> 2*8 ) & 0xFF;

	dma_ch->DESTADDR0 = (dest_addr >> 0*8 ) & 0xFF;	// destination is UART
	dma_ch->DESTADDR1 = (dest_addr >> 1*8 ) & 0xFF;
	dma_ch->DESTADDR2 = (dest_addr >> 2*8 ) & 0xFF;

	dma_ch->TRIGSRC = trigger;
	dma_ch->CTRLA = 0x84;	// enable channel, no repeat, burst=1, single shot mode
}
